package com.example.springboot.config;


import com.example.springboot.utils.JSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class MyStringRedisTemplate {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public StringRedisTemplate getStringRedisTemplate() {
        return this.stringRedisTemplate;
    }

    public <T> T setByJson(String key, T t, long time, TimeUnit unit) {
        if (t != null) {
            stringRedisTemplate.opsForValue().set(key, JSUtils.toJSONString(t), time, unit);
        }
        return t;
    }

    public String set(String key, String value, long timeout, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
        return value;
    }

    public <T> T getForJson(String key, Class<T> clazz) {
        String result = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.hasText(result)) {
            return JSUtils.parseObject(result, clazz);
        }
        return null;
    }

    public String get(String key) {
        if (null != key) {
            return stringRedisTemplate.opsForValue().get(key);
        }
        return null;
    }

    public void delete(String key) {
        if (null != key && stringRedisTemplate.hasKey(key)) {
            stringRedisTemplate.delete(key.toString());
        }
    }

    public void delete(Set key) {
        stringRedisTemplate.delete(key);
    }

    public <T> List<T> list(String key, Class<T> clazz) {
        String result = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.hasText(result)) {
            try {
                return JSUtils.parseArray(stringRedisTemplate.opsForValue().get(result), clazz);
            } catch (Exception e) {
//                log.error("解析异常", e);
                return null;
            }
        }
        return null;
    }

    public boolean hasKey(Object key) {
        if (null != key && stringRedisTemplate.hasKey(String.valueOf(key))) {
            return true;
        }
        return false;
    }

    /**
     * 如果键不存在则新增,存在则不改变已经有的值。
     *
     * @param key
     * @param value
     * @return
     */
    public String getAndSet(Object key, String value) {
        if (null != key) {
            return stringRedisTemplate.opsForValue().getAndSet(String.valueOf(key), value);
        }
        return null;
    }

    /**
     * 获取原来key键对应的值并重新赋新值
     *
     * @param key
     * @param value
     * @return
     */
    public boolean setIfAbsent(Object key, String value) {
        if (null != key && stringRedisTemplate.opsForValue().setIfAbsent(String.valueOf(key), value)) {
            return true;
        }
        return false;
    }

    /**
     * 更新缓存时间
     *
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, Integer time) {
        return stringRedisTemplate.expire(key, time, TimeUnit.MINUTES);
    }

    /**
     * 模糊查询获取相关key缓存
     *
     * @param prefix
     * @return
     */
    public Set<String> keys(String prefix) {
        return stringRedisTemplate.keys(prefix);
    }

    /**
     * 批量查询
     *
     * @param <T>
     * @param keys
     * @param clazz
     * @return
     */
    public <T> List<T> multiGetKeys(Set<String> keys, Class<T> clazz) {
        return JSUtils.parseArray(stringRedisTemplate.opsForValue().multiGet(keys).toString(), clazz);
    }

    /**
     * 加锁
     *
     * @param key 前缀+内容
     * @return 加锁结果
     */
    public boolean lock(String key) {
        // 可以设置返回true
        Boolean isLock = stringRedisTemplate.opsForValue().setIfAbsent(key, String.valueOf(System.currentTimeMillis()), 10, TimeUnit.MINUTES);
        return isLock != null && isLock;
    }

    /**
     * 解锁
     *
     * @param key 前缀+内容
     */
    public void unlock(String key) {
        Boolean result = stringRedisTemplate.hasKey(key);
        if (result != null && result) {
            stringRedisTemplate.opsForValue().getOperations().delete(key);
        }
    }

    /**
     * 统计key的数量
     */
    public long countExistingKeys(String pattern) {
        return stringRedisTemplate.keys(pattern).size();
    }
}
